package com.zonski.jbots.game.entity;

import java.util.Vector;

import com.zonski.jbots.engine.*;
import com.zonski.jbots.engine.entity.MovingEntity;
import com.zonski.jbots.engine.entity.AbstractMind;
import com.zonski.jbots.engine.entity.InstantMovementEffect;
import com.zonski.jbots.engine.entity.Mind;

import com.zonski.jbots.game.JBotsConstants;

/** 
 * spins around looking for a target, then moves in a specific direction 
 * when it senses something, explodes when it comes into contact with
 * something
 */
public class CometMind extends AbstractMind
{
    private int updates = 0;

    private static final int DEFAULT_LIFESPAN = 500;
    private static final Rectangle C_RECT = new Rectangle(0, 0, 0, 0);
    private static final Rectangle S_RECT = new Rectangle(1, 1, 1, 1);

    // NOTE : do not make spin wait 1 or strange behaviour will result
    private int spinWait = 2;
    private int lifespan = DEFAULT_LIFESPAN;
    private boolean vibrate;

    public CometMind()
    {
    }

    public void update(Engine engine)
    {
        int mode = getEntity().getMode();
        if(updates > lifespan || mode == Modes.DEAD)
        {
            if(mode == Modes.DEAD && this.vibrate)
            {
                this.getEntity().getDevice().vibrate(5);
                // TODO : explode?
            }
            this.getEntity().setRemovable(true);
        }else{
            if(mode == Modes.NONE)
            {
                MovingEntity movingEntity = (MovingEntity)this.getEntity();
                int direction = movingEntity.direction;
                // have a look in that direction for a target
                if(updates % spinWait == (spinWait-1) && 
                        Directions.isCardinal(direction))
                {
                    Room room = engine.getRoom();
                    Rectangle search = S_RECT;
                    int width = room.getWidth();
                    int height = room.getHeight();
                    Rectangle entityBounds = movingEntity.bounds;
                    switch(direction)
                    {
                        default:
                        case Directions.NORTH:
                            /*
                            search = new Rectangle(
                                    entityBounds.x, entityBounds.y,
                                    entityBounds.width, height);
                                    */

                            search.setLocation(
                                    entityBounds.x, entityBounds.y,
                                    entityBounds.width, height
                            );
                            break;
                        case Directions.SOUTH:
                            /*
                            search = new Rectangle(
                                    entityBounds.x, entityBounds.y-height,
                                    entityBounds.width,
                                    height+entityBounds.height);
                                    */
                            search.setLocation(
                                    entityBounds.x, entityBounds.y - height,
                                    entityBounds.width, height + entityBounds.height
                            );
                            break;
                        case Directions.EAST:
                            /*
                            search = new Rectangle(
                                    entityBounds.x, entityBounds.y,
                                    width, entityBounds.height);
                                    */
                            search.setLocation(
                                    entityBounds.x, entityBounds.y,
                                    width, entityBounds.height
                            );
                            break;
                        case Directions.WEST:
                            /*
                            search = new Rectangle(
                                    entityBounds.x-width, entityBounds.y,
                                    width+entityBounds.width,
                                    entityBounds.height);
                                    */

                            search.setLocation(
                                    entityBounds.x - width, entityBounds.y,
                                    entityBounds.width + width, entityBounds.height
                            );
                            break;
                    }
                    boolean isInteresting = false;
                    int minProx = Integer.MAX_VALUE;

                    RoomStateMatrix stateMatrix = engine.getStateMatrix();
                    Rectangle tileBounds = stateMatrix.convertToTileBounds(search, C_RECT);
                    for(int tx = tileBounds.x; tx<tileBounds.rightEdge; tx++)
                    {
                        for(int ty = tileBounds.y; ty<tileBounds.bottomEdge; ty++)
                        {
                            QuickVector entities;
                            entities = stateMatrix.getEntitiesOnTile(tx, ty);
                            if(entities != null)
                            {
                                for(int i=entities.size(); i > 0; )
                                {
                                    i--;
                                    Entity found = (Entity)entities.elementAt(i);
                                    Rectangle foundBounds = found.bounds;
                                    boolean isBot = JBotsConstants.isBot(found.entityType.getId());
                                    boolean isRock = JBotsConstants.isObstacle(found.entityType.getId());
                                    if(foundBounds.overlaps(search) &&
                                            found.layerId != movingEntity.layerId &&
                                            (isBot || isRock))
                                    {
                                        int x = foundBounds.x - entityBounds.x;
                                        int y = foundBounds.y - entityBounds.y;
                                        int prox = x*x+y*y;
                                        if(prox < minProx)
                                        {
                                            minProx = prox;
                                            isInteresting = isBot;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if(isInteresting)
                    {
                        movingEntity.setTargetDirection(direction);
                        movingEntity.setTargetVelocity(200);
                        movingEntity.setMode(Modes.WALKING);
                        movingEntity.getDevice().play(JBotsConstants.COMET, 1);
                    }
                }
                if(getEntity().getMode() == Modes.NONE)
                {
                    if(updates % spinWait == 0)
                    {
                        direction = Directions.addDirection(direction, 2);
                        movingEntity.setTargetDirection(direction);
                        movingEntity.effectiveModeUpdates = 0;
                    }
                }
            }else if(mode == Modes.WALKING){

            }
        }
        updates++;
    }

    public void collision(Engine engine, CollisionData data)
    {
        super.collision(engine, data);
        this.vibrate = (data.with.layerId != this.getEntity().layerId &&
                JBotsConstants.isBot(data.with.entityType.getId())) || this.vibrate;
    }

    public Mind copy()
    {
        return new CometMind();
    }
}
